#ifndef __HUD_H__
#define __HUD_H__

// Copyright (c) 2010 Omer Goshen



#include "Ogre.h"
#include <OgreTextAreaOverlayElement.h>

#include "MudBath.h"

using namespace Ogre;

class App;

class HudRenderListener;

class HudMaterialSwitcher : public MaterialManager::Listener
{
private:
	Technique   *mLastTechnique;


public:
	HudMaterialSwitcher() : mLastTechnique(0) {}
	~HudMaterialSwitcher() {}

	virtual Technique *handleSchemeNotFound(unsigned short schemeIndex, const Ogre::String &schemeName,
	                                        Ogre::Material *originalMaterial, unsigned short lodIndex,
	                                        const Ogre::Renderable *rend)
	{
		const SubEntity *subEntity = static_cast<const SubEntity *>(rend);

		ResourcePtr res = MaterialManager::getSingleton().load("PlainColor", ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME);
		Technique* t = static_cast<MaterialPtr>(res)->getTechnique(0);

		const_cast<SubEntity *>(subEntity)->setCustomParameter(1, Vector4(1,0,1,1));

		return t;
	}

};

class HudRenderListener : public RenderTargetListener
{
private:
	HudMaterialSwitcher *mMaterialListener;
	SceneManager* mSceneMgr;
	OverlayManager* olm;

public:
	HudRenderListener(HudMaterialSwitcher *switcher, SceneManager* mgr) :
		mMaterialListener(switcher),
		mSceneMgr(mgr),
		olm(OverlayManager::getSingletonPtr())
	{
	}
	~HudRenderListener() {}

	virtual void preRenderTargetUpdate(const RenderTargetEvent &evt)
	{
//		mSceneMgr->getRootSceneNode()->setVisible(false, false);
//		mSceneMgr->getRootSceneNode()->flipVisibility(true);

		SceneNode::ChildNodeIterator it1 = mSceneMgr->getRootSceneNode()->getChildIterator();
		while(it1.hasMoreElements())
			{
				dynamic_cast<SceneNode*>(it1.getNext())->flipVisibility();
			}


		OverlayManager::OverlayMapIterator it = olm->getOverlayIterator();
		while(it.hasMoreElements())
			{
				Overlay* o = it.getNext();
				if(o->getName()=="Console") continue;
				o->show();
			}
	}

	virtual void postRenderTargetUpdate(const RenderTargetEvent &evt)
	{
//		mSceneMgr->getRootSceneNode()->setVisible(true, false);
//		mSceneMgr->getRootSceneNode()->flipVisibility(true);

		SceneNode::ChildNodeIterator it1 = mSceneMgr->getRootSceneNode()->getChildIterator();
		while(it1.hasMoreElements())
			{
				dynamic_cast<SceneNode*>(it1.getNext())->flipVisibility();
			}

		OverlayManager::OverlayMapIterator it = olm->getOverlayIterator();
		while(it.hasMoreElements())
			{
				Overlay* o = it.getNext();
				if(o->getName()=="Console") continue;
				o->hide();
			}
	}
};

class HUD : public FrameListener
{
public:
	HUD(Ogre::Root* root, SceneManager *sceneMgr, Camera* cam, RenderTarget *renderTarget);
	virtual ~HUD();

	bool frameStarted(const FrameEvent& e) { return true; }
	bool frameEnded(const FrameEvent& e) { return true; }
	
	void toggle();

	void print(const Ogre::String&);

protected:
	HudMaterialSwitcher *mMaterialSwitchListener;
	HudRenderListener *mHudTargetListener;


	Root* mRoot;
	SceneManager* mSceneMgr;
	Camera *mCamera;
	RenderTarget *mRenderTarget;


	TexturePtr mTexture;
	RenderTexture *mRenderTexture;
	uint8 *mBuffer;
	PixelBox *mPixelBox;

	Overlay* overlay;
	OverlayContainer* panel;

};

#endif
